package com.my.test.spring.aop;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

/**
 * Created by Administrator on 2017-4-19.
 */

@Aspect
@Component
public class ServiceAop {

    @Pointcut("execution(* com.my.test.spring.service.*.*(..))")
    private void httpUtilAspectPointCut(){};

    @Before("httpUtilAspectPointCut()")
    public void before()  {
    }

    @Around("httpUtilAspectPointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        Object result = null;
//        this.before(point);//相当于前置通知
        long start = System.currentTimeMillis();
        String log = "";
        try {
            String className = point.getTarget().getClass().getName();
            String methodName = point.getSignature().getName();
            Object[] args = point.getArgs();
            for(Object o:args){
                System.out.println(o);
            }
            result = point.proceed();
            log = "【注解-前置通知】:" + className + "类的"
                    + methodName + "方法开始了,返回结果="+result;

//            this.afterReturn(); //相当于后置通知
        } catch (Throwable e) {
//            this.afterThrowing();  //相当于异常抛出后通知
            StackTraceElement[] stacks = e.getStackTrace();
            throw e;
        }finally{
//            this.after();  //相当于最终通知

            String methodName = "";
            StackTraceElement[] ab = Thread.currentThread().getStackTrace();
            for (StackTraceElement stackTraceElement : ab) {
                System.out.println("className="+stackTraceElement.getClassName()+",method="+stackTraceElement.getMethodName());
                if (isParentMethodName(stackTraceElement,this.getClass().getName())) {
                    if (methodName.isEmpty()) {
                        methodName = stackTraceElement.getClassName() + "."
                                + stackTraceElement.getMethodName();
                    }
                }
            }
            System.out.println(log+",methodName="+methodName+",消耗的时间："+(System.currentTimeMillis()-start));
        }
        return result;
    }

    @After("httpUtilAspectPointCut()")
    public void after()  {
    }



    /**
     * 记录方法的上级方法时判断堆栈是否为父方法
     * @param stackTraceElement
     * @param aopClassName
     * @return
     * @author zhaohailong
     * @date 20160627
     */
    public static boolean isParentMethodName(StackTraceElement stackTraceElement,String aopClassName){
        if (stackTraceElement.getClassName().indexOf("com.my") >= 0
                &&!stackTraceElement.getClassName().equals(aopClassName)) {
            if (stackTraceElement.getClassName().indexOf("$") < 0) {
                return true;
            }else if (stackTraceElement.getMethodName().equals("run")) {
                return true;
            }
        }
        return false;
    }
}
